package net.ak.aspect;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Aspect
public class EntryExitLoggingAspect {
	private static final Logger LOGGER = LoggerFactory.getLogger(EntryExitLoggingAspect.class);

	@Around("within(net.ak..*)")
	public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
		LOGGER.debug("Entry: [{}]", joinPoint.getSignature());

		StringBuilder arguments = new StringBuilder();
		for (Object arg : joinPoint.getArgs()) {
			arguments.append(arg).append(",");
		}
		if (StringUtils.isNotBlank(arguments)) {
			arguments.deleteCharAt(arguments.length() - 1);
		}
		LOGGER.debug("Arguments: [{}]", arguments.toString());

		StopWatch stopWatch = new StopWatch();
		Object result;
		try {
			stopWatch.start();
			result = joinPoint.proceed();
			stopWatch.stop();
			LOGGER.debug("Return value: [{}]", result);
		} catch (Throwable ex) {
			stopWatch.stop();
			LOGGER.warn("Exception: ", ex);
			throw ex;
		} finally {
			LOGGER.debug("Exit: [[{}], Execution Time: [{}ms]]", joinPoint.getSignature().getName(),
					stopWatch.getTime());
		}

		return result;
	}
}
